package com.jrx.anytxn.investor.service.impl;

import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.BeanUtils;
import com.jrx.anytxn.investor.bean.InvestorTransferBean;
import com.jrx.anytxn.investor.bean.InvestorTransferSaveBean;
import com.jrx.anytxn.investor.constant.TransBizConstant;
import com.jrx.anytxn.investor.entity.AmAccountMainInvestorInfo;
import com.jrx.anytxn.investor.entity.TlGlInterfaceInvestorInfo;
import com.jrx.anytxn.investor.entity.TlInvestorLoanChange;
import com.jrx.anytxn.investor.service.IInvestorGlInterfaceService;
import com.jrx.anytxn.investor.service.IInvestorLoanChangeService;
import com.jrx.anytxn.investor.service.IInvestorTransferTypeStrategy;
import com.jrx.anytxn.param.constant.ErrorMsgConstant;
import com.jrx.anytxn.transaction.bean.DelqAccountBean;
import com.jrx.anytxn.transaction.bean.DelqClassifyBean;
import com.jrx.anytxn.transaction.bean.DelqNonAccrualBean;
import com.jrx.anytxn.transaction.bean.DelqParamBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.Date;
import java.util.Optional;

/**
 * 交易账户转列策略
 *
 * @author liuyang
 * @date 2020-05-27
 **/
@Service
public class InvestorAcctTransferTypeStrategy implements IInvestorTransferTypeStrategy<AmAccountMainInvestorInfo> {
    
    private static final Logger logger = LoggerFactory.getLogger(InvestorAcctTransferTypeStrategy.class);

    @Autowired
    private IInvestorGlInterfaceService glInterfaceService;
    @Autowired
    private IInvestorLoanChangeService loanChangeService;

    /**
     * 账户外转列处理 会计状态升级，转表外，五级分类升级
     *
     * @param transferBean 转列辅助Bean
     * @return InvestorTransferSaveBean 转列保存Bean
     * @throws TxnException
     * @author liuyang
     * @date 2020-05-27
     */
    @Override
    public InvestorTransferSaveBean transferOut(InvestorTransferBean<AmAccountMainInvestorInfo> transferBean) throws TxnException {
        AmAccountMainInvestorInfo acct = transferBean.getTransferObject();
        logger.info("交易账户外转列acct:{}", BeanUtils.toMap(acct));
        DelqParamBean delqParamBean = transferBean.getDelqParamBean();
        Date bussinessDate = transferBean.getBussinessDate();
        int accountingDays = transferBean.getAccountingDays();
        int nonAccrualDays = transferBean.getNonAccrualDays();
        int classifyDays = transferBean.getClassifyDays();
        InvestorTransferSaveBean transferSaveBean = new InvestorTransferSaveBean();
        AmAccountMainInvestorInfo updateAcct = new AmAccountMainInvestorInfo();
        updateAcct.setId(acct.getId());
        updateAcct.setCustomerId(acct.getCustomerId());
        updateAcct.setTenantId(acct.getTenantId());
        String tempAccountStatus = acct.getAccountingPhase();
        boolean isUpdate = false;

        //五级分类
        String classify = delqParamBean.getDelqClassifyBeanList().stream()
                .filter(bean -> classifyDays >= bean.getClassifyDays())
                .map(DelqClassifyBean::getClassifyType)
                .max(String::compareTo)
                .orElse("0");

        //如果与原状态不同则修改
        if (!classify.equals(acct.getLoanClassify())) {
            isUpdate = true;
            updateAcct.setLoanClassify(classify);
            acct.setLoanClassify(classify);
        }

        //会计状态转列处理，获取转列天数小于延滞天数，取会计状态最大的那个
        DelqAccountBean delqAccountBean = delqParamBean.getDelqAccountBeanList().stream()
                .filter(bean -> bean.getAccountType().contains(acct.getAccountType()))
                .filter(bean -> accountingDays >= bean.getTransferDays())
                .filter(bean -> TransBizConstant.TRANSFER_FLAG_1.equals(bean.getTransferFlag()))
                .max(Comparator.comparing(DelqAccountBean::getAccountingPhase))
                .orElseThrow(() -> new TxnBizException(ErrorMsgConstant.SYSTEM_PARAMETER_EXISTS));

        String accountingPhase = delqAccountBean.getAccountingPhase();
        logger.info("会计状态转列参数为:{},原状态为:{}", BeanUtils.toMap(delqAccountBean), accountingPhase);
        //如果允许转列
        if (delqAccountBean.getAccountingPhase().compareTo(tempAccountStatus)>0) {
            isUpdate = true;
            String txnCode = delqAccountBean.getTxnCode();
            String eventCode = delqAccountBean.getEventCode();
            updateAcct.setAccountingPhase(accountingPhase);
            acct.setAccountingPhase(accountingPhase);
            TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(acct, acct.getCurrBalance().subtract(acct.getTaxAmt()), txnCode, tempAccountStatus, bussinessDate);
            logger.info("会计状态转列GL流水为:{}", BeanUtils.toMap(glInterfaceInfo));
            Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

            TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(acct.getAccountType(),acct.getCurrBalance().subtract(acct.getTaxAmt()),eventCode,tempAccountStatus,accountingPhase);
            transferSaveBean.getLoanChangeList().add(loanChange);
        }

        //应计/非应计，根据交易账户类型获取对应的参数
        DelqNonAccrualBean delqNonAccrualBean = delqParamBean.getDelqNonAccrualBeanMap().get(acct.getAccountType());
        logger.info("应计/非应计状态转列参数为:{},原状态为:{}", BeanUtils.toMap(delqNonAccrualBean), acct.getNonAccrualsFlag());
        //延滞天数>=转列天数
        if (nonAccrualDays >= delqNonAccrualBean.getTransDays()) {
            //允许转列
            if (TransBizConstant.TRANSFER_FLAG_1.equals(delqNonAccrualBean.getNonAccrualFlag())
                    && TransBizConstant.NON_ACCRUALS_FLA_0.equals(acct.getNonAccrualsFlag())) {
                isUpdate = true;
                String txnCode = delqNonAccrualBean.getNonTxnCode();
                String taxTxnCode = delqNonAccrualBean.getNonTaxTxnCode();
                updateAcct.setNonAccrualsFlag(TransBizConstant.NON_ACCRUALS_FLA_1);
                TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(acct, acct.getCurrBalance().subtract(acct.getTaxAmt()), txnCode, tempAccountStatus, bussinessDate);
                TlGlInterfaceInvestorInfo taxGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(acct, acct.getTaxAmt(), taxTxnCode, tempAccountStatus, bussinessDate);
                logger.info("应计/非应计状态转列GL流水为:{}", BeanUtils.toMap(glInterfaceInfo));
                logger.info("税金应计/非应计状态转列GL流水为:{}", BeanUtils.toMap(taxGlInterfaceInfo));
                Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));
                Optional.ofNullable(taxGlInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

                TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(acct.getAccountType(),acct.getCurrBalance().subtract(acct.getTaxAmt()),TransBizConstant.EVENT_CODE_TN,TransBizConstant.NON_ACCRUALS_FLA_A,TransBizConstant.NON_ACCRUALS_FLA_N);
                transferSaveBean.getLoanChangeList().add(loanChange);
            }

            //整笔转逾期,此时处理为逾期天数不满足转逾期条件的账户
            if (TransBizConstant.TRANSFER_FLAG_2.equals(delqNonAccrualBean.getNonAccrualFlag())
                    && TransBizConstant.ACCOUNTING_PHASE_0.equals(acct.getAccountingPhase())) {
                isUpdate = true;
                delqAccountBean = delqParamBean.getDelqAccountBeanList().stream()
                        .filter(bean -> bean.getAccountType().contains(acct.getAccountType()))
                        .filter(bean -> TransBizConstant.ACCOUNTING_PHASE_1.equals(bean.getAccountingPhase()))
                        .findFirst()
                        .orElseThrow(() -> new TxnBizException(ErrorMsgConstant.SYSTEM_PARAMETER_EXISTS));
                String txnCode = delqAccountBean.getTxnCode();
                String eventCode = delqAccountBean.getEventCode();
                updateAcct.setAccountingPhase(TransBizConstant.ACCOUNTING_PHASE_1);
                TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(acct, acct.getCurrBalance(), txnCode, tempAccountStatus, bussinessDate);
                logger.info("整笔转逾期当期转逾期GL流水为:{}", BeanUtils.toMap(glInterfaceInfo));
                Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

                TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(acct.getAccountType(),acct.getCurrBalance().subtract(acct.getTaxAmt()),eventCode,TransBizConstant.ACCOUNTING_PHASE_0,TransBizConstant.ACCOUNTING_PHASE_1);
                transferSaveBean.getLoanChangeList().add(loanChange);
            }
        }

        if (isUpdate) {
            transferSaveBean.setUpdateAcct(updateAcct);
            return transferSaveBean;
        }

        return null;
    }

    /**
     * 账户内转列出处理 会计状态降级，转应计，五级分类降级
     *
     * @param transferBean 转列辅助Bean
     * @return InvestorTransferSaveBean 转列保存Bean
     * @throws TxnException
     * @author liuyang
     * @date 2020-05-27
     */
    @Override
    public InvestorTransferSaveBean transferIn(InvestorTransferBean<AmAccountMainInvestorInfo> transferBean) throws TxnException {
        AmAccountMainInvestorInfo acct = transferBean.getTransferObject();
        logger.info("交易账户内转列acct:{}", BeanUtils.toMap(acct));
        DelqParamBean delqParamBean = transferBean.getDelqParamBean();
        Date bussinessDate = transferBean.getBussinessDate();
        int accountingDays = transferBean.getAccountingDays();
        int nonAccrualDays = transferBean.getNonAccrualDays();
        int classifyDays = transferBean.getClassifyDays();
        InvestorTransferSaveBean transferSaveBean = new InvestorTransferSaveBean();
        AmAccountMainInvestorInfo updateAcct = new AmAccountMainInvestorInfo();
        updateAcct.setId(acct.getId());
        updateAcct.setCustomerId(acct.getCustomerId());
        updateAcct.setTenantId(acct.getTenantId());
        String tempAccountStatus = acct.getAccountingPhase();
        boolean isUpdate = false;

        //五级分类
        String classify = delqParamBean.getDelqClassifyBeanList().stream()
                .filter(bean -> classifyDays >= bean.getClassifyDays())
                .map(DelqClassifyBean::getClassifyType)
                .max(String::compareTo)
                .orElse("0");

        //如果与原状态不同则修改
        if (!classify.equals(acct.getLoanClassify())) {
            isUpdate = true;
            updateAcct.setLoanClassify(classify);
            acct.setLoanClassify(classify);
        }

        //应计/非应计，根据交易账户类型获取对应的参数
        DelqNonAccrualBean delqNonAccrualBean = delqParamBean.getDelqNonAccrualBeanMap().get(acct.getAccountType());
        //会计状态转列处理，获取转列天数小于延滞天数并且允许转列的参数，取会计状态最大的那个
        DelqAccountBean delqAccountBean = delqParamBean.getDelqAccountBeanList().stream()
                .filter(bean -> bean.getAccountType().contains(acct.getAccountType()))
                .filter(bean -> accountingDays >= bean.getTransferDays())
                .filter(bean -> TransBizConstant.TRANSFER_FLAG_1.equals(bean.getTransferFlag()))
                .max(Comparator.comparing(DelqAccountBean::getAccountingPhase))
                .orElseThrow(() -> new TxnBizException(ErrorMsgConstant.SYSTEM_PARAMETER_EXISTS));

        //判断会计状态是否不等，则更新会计状态，并且生成转列GL流水
        //本金应计/非应计方式如果为整笔转逾期。则转回时统一在会记转列处理
        String accountingPhase = delqAccountBean.getAccountingPhase();
        logger.info("会计状态转列参数为:{},原状态为:{}", BeanUtils.toMap(delqAccountBean), tempAccountStatus);
        if (!tempAccountStatus.equals(accountingPhase)) {
            if(TransBizConstant.ACCOUNT_TYPE_06.equals(transferBean.getAccountType())
                && transferBean.getMaxDelqDays() >= delqNonAccrualBean.getTransDays()
                && TransBizConstant.TRANSFER_FLAG_2.equals(delqNonAccrualBean.getNonAccrualFlag())) {
                //主要用于排除逾期天数不满足转逾期，但是订单状态为非应计的交易账户回转
                logger.info("本金交易账户,如果转列方式为整笔转逾期，并且当前订单为非应计状态，则不进行会记状态转列");
            }else {
                isUpdate = true;
                String txnCode = delqAccountBean.getTxnCode();
                String eventCode = delqAccountBean.getEventCode();
                updateAcct.setAccountingPhase(accountingPhase);
                acct.setAccountingPhase(accountingPhase);
                //金额为除税金额（利息）
                TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(acct, acct.getCurrBalance().subtract(acct.getTaxAmt()), txnCode, tempAccountStatus, bussinessDate);
                logger.info("会计状态转列GL流水为:{}", BeanUtils.toMap(glInterfaceInfo));
                Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

                TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(acct.getAccountType(),acct.getCurrBalance().subtract(acct.getTaxAmt()),eventCode,tempAccountStatus,accountingPhase);
                transferSaveBean.getLoanChangeList().add(loanChange);
            }
        }


        logger.info("应计/非应计状态转列参数为:{},原状态为:{}", BeanUtils.toMap(delqNonAccrualBean), acct.getNonAccrualsFlag());
        //延滞天数<转列天数
        if (nonAccrualDays < delqNonAccrualBean.getTransDays()) {
            //允许转列
            if (TransBizConstant.TRANSFER_FLAG_1.equals(delqNonAccrualBean.getNonAccrualFlag())
                    && TransBizConstant.NON_ACCRUALS_FLA_1.equals(acct.getNonAccrualsFlag())) {
                isUpdate = true;

                // 表外交易的转回表内 交易码转为T58XXX
                String txnCode = delqNonAccrualBean.getInNonTxnCode();
                String taxTxnCode = delqNonAccrualBean.getInNonTaxTxnCode();

                //表内交易的转表外后转回表内 交易码转为T56XXX 表内交易账户txnCode为5XXXX 表外交易账户txnCode为9XXXX
                if(!TransBizConstant.ACCOUNT_TYPE_06.equals(acct.getAccountType()) && "5".equals(acct.getTxnCode().substring(1,2))){
                    txnCode = txnCode.substring(0,1)+(Integer.parseInt(txnCode.substring(1))-2000);
                    taxTxnCode = taxTxnCode.substring(0,1)+(Integer.parseInt(taxTxnCode.substring(1))-2000);
                }
                updateAcct.setNonAccrualsFlag(TransBizConstant.NON_ACCRUALS_FLA_0);
                TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(acct, acct.getCurrBalance().subtract(acct.getTaxAmt()), txnCode, tempAccountStatus, bussinessDate);
                TlGlInterfaceInvestorInfo taxGlInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(acct,acct.getTaxAmt() , taxTxnCode, tempAccountStatus, bussinessDate);
                logger.info("应计/非应计状态转列GL流水为:{}", BeanUtils.toMap(glInterfaceInfo));
                logger.info("税金应计/非应计状态转列GL流水为:{}", BeanUtils.toMap(taxGlInterfaceInfo));
                Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));
                Optional.ofNullable(taxGlInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

                TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(acct.getAccountType(),acct.getCurrBalance().subtract(acct.getTaxAmt()),TransBizConstant.EVENT_CODE_TA,TransBizConstant.NON_ACCRUALS_FLA_N,TransBizConstant.NON_ACCRUALS_FLA_A);
                transferSaveBean.getLoanChangeList().add(loanChange);

            }
        }

        if (isUpdate) {
            transferSaveBean.setUpdateAcct(updateAcct);
            return transferSaveBean;
        }
        return null;
    }
}
